# -*- coding: utf-8 -*-
import os,sys,re
from CMDSets import *
# https://blog.csdn.net/cn_wk/article/details/76933956

def command_builder(f):
    def __command_wrapper(device,k,v):
        _vf_ = f(v)
        def __inner_wrapper(*args,**kwargs):
            _idx = v.count('{}')
            _cmd = _vf_(*args[:_idx])
            _args = [] if _idx >= len(args) else list(args[_idx:])
            _fkey_=k
            if 'action' in kwargs:
                _fkey_ = kwargs['action']
                del kwargs['action']
            if device and hasattr(device, _fkey_):
                _df_ = getattr(device, _fkey_)
                _hasArgs = _df_.__code__.co_argcount > 1
                _hasKwargs = _df_.__defaults__ != None
                _hasCmd = _hasArgs and _df_.__code__.co_varnames[1] in ['cmd','command']
                if _hasCmd: _args.insert(0,_cmd)
                if _hasArgs and _hasKwargs:
                    return _df_(*_args, **kwargs)
                elif _hasArgs:
                    return _df_(*_args)
                elif _hasKwargs:
                    return _df_(**kwargs)
                else:
                    return _df_()
            else:
                return _cmd
        return __inner_wrapper
    return __command_wrapper

@command_builder
def _format_value(v):
    def _build_format_(*args):
        return v.format(*args)
    return _build_format_

def _get_attr_func_(d, k):
    if k in d.keys():
        v = d[k]
        if isinstance(v, dict):
            v['__device__']=d['__device__']
            v['__default_action__']=d['__default_action__']
            return CMDProtocolBasic(v)
        else:
            _nk = k if hasattr(d['__device__'],k) else d['__default_action__']
            return _format_value(d['__device__'],_nk,v)

class CMDProtocolBasic(dict):
    def __getattr__(self,k):
        return _get_attr_func_(self,k)

class DeviceCmdSetsController(object):
    def __init__(self,device=None,cmdextends=None,defaultAction='write',identifier=''):
        self._dataBasic = CMDProtocolBasic(CMDSetsBasic)
        self._dataBasic['__device__']=device
        self._dataBasic['__default_action__'] = defaultAction
        self.identifier = str(identifier)
        if cmdextends:
            self.check_instruction_set(cmdextends)

    def check_instruction_set(self,data):
        def __inner_check_items(d,src):
            for k,v in d.items():
                if isinstance(v,dict):
                    if k in src:
                        __inner_check_items(v,src[k])
                        continue
                src[k]=v
        __inner_check_items(data,self._dataBasic)

    def __getattr__(self,k):
        return _get_attr_func_(self._dataBasic,k)

    def __getitem__(self,k):
        if k and k == 'identifier':
            return self.identifier
        if k and k == 'device':
             return self._dataBasic['__device__']

class _device_controller_doe(object):
    '''UART or TEK contriller'''
    def test(self,x):
        print('device_test')
    def write(self,cmd,bybyte):
        print('device_write_parameters==',cmd,bybyte)
    def query(self,cmd):
        # print(timeout)
        print('device_query_parameters==',cmd)

if __name__ == '__main__':
    device = DeviceCmdSetsController(device=_device_controller_doe(),cmdextends=TEKMSO4104B_CmdSets)
    device.vertical.label.set(1,'aaa','xvar',action='write')



